package com.xj.algorithm.leetcode;

/**
 * 完美数
 */
public class L507_完美数 {

    /**
     * 对于一个 正整数，如果它和除了它自身以外的所有正因子之和相等，我们称它为“完美数”。
     * <p>
     * 给定一个 整数 n， 如果他是完美数，返回 True，否则返回 False
     * <p>
     *  
     * <p>
     * 示例：
     * <p>
     * 输入: 28
     * 输出: True
     * 解释: 28 = 1 + 2 + 4 + 7 + 14
     *  
     * <p>
     * 提示：
     * <p>
     * 输入的数字 n 不会超过 100,000,000. (1e8)
     */
    public static void main(String[] args) {
        System.out.println(checkPerfectNumber(28));
        System.out.println(checkPerfectNumber(99999997));

        System.out.println(checkPerfectNumberOffice(28));
        System.out.println(checkPerfectNumberOffice(99999997));
    }

    //自己的解法：暴力法,要超时。只遍历sqrt(num)就不超时
    public static boolean checkPerfectNumber(int num) {
        if (num <= 1) {
            return false;
        }
        int sum = 0;
        for (int i = 1; i <= Math.sqrt(num); i++) {
            if (i == 1) {
                sum = sum + i;
            } else if (num % i == 0) {
                sum = sum + i;
                sum = sum + (num / i);
            }
        }

        return sum == num;
    }


    //官方解法：公式法，欧几里得-欧拉定理：
    // 每个偶完全数都可以写成 2^{p-1}*(2^p-1),p是素数
    //比如：6=2^1*(2^2-1)
    public static boolean checkPerfectNumberOffice(int num) {
        int[] primes = new int[]{2, 3, 5, 7, 13, 17, 19, 31};
        for (int prime : primes) {
            if ((1 << (prime - 1)) * ((1 << prime) - 1) == num)
                return true;
        }
        return false;
    }

}
